#include "gfx-object.h"
#include "gfx-pipeline.h"
#include "gfx-texture.h"
#include "gfx-mgr.h"

GfxObject::GfxObject(GfxObjectTypeE type)
{
    this->_isOK = false;
    this->_color[0] = 1.0f;
    this->_color[1] = 1.0f;
    this->_color[2] = 1.0f;
    this->_color[3] = 1.0f;
    this->_type = type;
    this->_pipeline = nullptr;
    this->_texture = nullptr;

}

void GfxObject::setVertexs(std::vector<float> points, std::vector<float> colors, std::vector<float> normals, std::vector<float> uvs, std::vector<uint32_t> indices)
{
    this->_cleanupBuffers();
    // 验证数据完整性
    size_t vertexCount = points.size() / 4; // 每个顶点4个float (x,y,z,w)
    if (vertexCount == 0 ||
        colors.size() != vertexCount * 4 ||
        normals.size() != vertexCount * 3 ||
        uvs.size() != vertexCount * 2 ||
        indices.size() == 0)
    {
        std::cerr << "Invalid vertex data sizes!" << std::endl;
        return;
    }
    this->_indexSize = indices.size();

    std::vector<float> interleavedVertices;
    interleavedVertices.reserve(vertexCount * (4 + 4 + 3 + 2)); // position + color + normal + uv

    for (size_t i = 0; i < vertexCount; ++i)
    {
        // 添加位置 (4 floats)
        interleavedVertices.insert(interleavedVertices.end(),
                                   points.begin() + i * 4,
                                   points.begin() + (i + 1) * 4);

        // 添加颜色 (4 floats)
        interleavedVertices.insert(interleavedVertices.end(),
                                   colors.begin() + i * 4,
                                   colors.begin() + (i + 1) * 4);

        // 添加法线 (3 floats)
        interleavedVertices.insert(interleavedVertices.end(),
                                   normals.begin() + i * 3,
                                   normals.begin() + (i + 1) * 3);

        // 添加UV (2 floats)
        interleavedVertices.insert(interleavedVertices.end(),
                                   uvs.begin() + i * 2,
                                   uvs.begin() + (i + 1) * 2);
    }
    // 顶点缓冲区
    GfxMgr::getInstance()->createBuffer(
        VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
        VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
        &this->_vertexBuffer,
        &this->_vertexMemory,
        interleavedVertices.size() * sizeof(float), // 总字节数
        interleavedVertices.data()                  // 数据指针
    );

    // 索引缓冲区（不变）
    GfxMgr::getInstance()->createBuffer(
        VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
        VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
        &this->_indexBuffer,
        &this->_indexMemory,
        indices.size() * sizeof(uint32_t),
        indices.data());
}
void GfxObject::_cleanupBuffers()
{
    vkDeviceWaitIdle(GfxMgr::getInstance()->getVulkanDevice());

    if (_vertexBuffer != VK_NULL_HANDLE)
    {
        vkDestroyBuffer(GfxMgr::getInstance()->getVulkanDevice(), _vertexBuffer, nullptr);
        _vertexBuffer = VK_NULL_HANDLE;
    }
    if (_vertexMemory != VK_NULL_HANDLE)
    {
        vkFreeMemory(GfxMgr::getInstance()->getVulkanDevice(), _vertexMemory, nullptr);
        _vertexMemory = VK_NULL_HANDLE;
    }
    if (_indexBuffer != VK_NULL_HANDLE)
    {
        vkDestroyBuffer(GfxMgr::getInstance()->getVulkanDevice(), _indexBuffer, nullptr);
        _indexBuffer = VK_NULL_HANDLE;
    }
    if (_indexMemory != VK_NULL_HANDLE)
    {
        vkFreeMemory(GfxMgr::getInstance()->getVulkanDevice(), _indexMemory, nullptr);
        _indexMemory = VK_NULL_HANDLE;
    }
}

void GfxObject::setPipeline(GfxPipeline *pipeline)
{
    this->_pipeline = pipeline;
    this->_createFramebuffers();
    if (this->_texture == nullptr)
    {
        return;
    }
    this->_updateDescriptorSet();
}
void GfxObject::_createFramebuffers()
{
    this->_cleanupFramebuffers();

    std::cout << "create framebuffers start..." << std::endl;
    this->_swapChainFramebuffers.resize(GfxMgr::getInstance()->getSwapChainImageViews().size());

    for (size_t i = 0; i < GfxMgr::getInstance()->getSwapChainImageViews().size(); i++)
    {
        VkImageView attachments[] = {GfxMgr::getInstance()->getSwapChainImageViews()[i]};
        VkFramebufferCreateInfo framebufferInfo = {};
        framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
        framebufferInfo.renderPass = this->_pipeline->getPass()->getVkRenderPass();

        framebufferInfo.attachmentCount = 1;                                         // 指定附着的个数
        framebufferInfo.pAttachments = attachments;                                  // 渲染流程对象用于描述附着信息的pAttachment数组
        framebufferInfo.width = GfxMgr::getInstance()->getSwapChainExtent().width;   // width和height用于指定帧缓冲的大小
        framebufferInfo.height = GfxMgr::getInstance()->getSwapChainExtent().height; // 交换链图像都是单层，layers设置为1
        framebufferInfo.layers = 1;

        if (vkCreateFramebuffer(GfxMgr::getInstance()->getVulkanDevice(), &framebufferInfo, nullptr, &this->_swapChainFramebuffers[i]) != VK_SUCCESS)

        {
            throw std::runtime_error("Failed to create framebuffer!");
        }
    }
    std::cout << "create framebuffers success..." << std::endl;

    this->_commandBuffers.resize(this->_swapChainFramebuffers.size());
    VkCommandBufferAllocateInfo allocInfo{};
    allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
    allocInfo.commandPool = GfxMgr::getInstance()->getCommandPool();
    allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
    allocInfo.commandBufferCount = (uint32_t)this->_commandBuffers.size();

    if (vkAllocateCommandBuffers(GfxMgr::getInstance()->getVulkanDevice(), &allocInfo, this->_commandBuffers.data()) != VK_SUCCESS)
    {
        throw std::runtime_error("Failed to allocate command buffers!");
    }
    std::cout << "create framebuffers success111..." << std::endl;
}
void GfxObject::_cleanupFramebuffers()
{
    if (!this->_commandBuffers.empty())
    {
        vkFreeCommandBuffers(GfxMgr::getInstance()->getVulkanDevice(), GfxMgr::getInstance()->getCommandPool(), static_cast<uint32_t>(this->_commandBuffers.size()), this->_commandBuffers.data());
        this->_commandBuffers.clear();
    }
    for (auto framebuffer : this->_swapChainFramebuffers)
    {
        vkDestroyFramebuffer(GfxMgr::getInstance()->getVulkanDevice(), framebuffer, nullptr);
    }
    this->_swapChainFramebuffers.clear();
}
void GfxObject::setClear(bool clear)
{
    this->_isClear = clear;
}
void GfxObject::setColor(float r, float g, float b, float a)
{
    this->_color[0] = r;
    this->_color[1] = g;
    this->_color[2] = b;
    this->_color[3] = a;
}
void GfxObject::setTexture(GfxTexture *texture)
{
    std::cout << "set texture start..." << std::endl;
    this->_texture = texture;
    if (this->_pipeline == nullptr)
    {
        return;
    }
    std::cout << "set texture success..." << std::endl;

    this->_updateDescriptorSet();
}

void GfxObject::_updateDescriptorSet()
{
    std::vector<VkDescriptorSetLayout> layouts(this->_swapChainFramebuffers.size(), this->_pipeline->getDescriptorSetLayout());
    VkDescriptorSetAllocateInfo allocInfo{};
    allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
    allocInfo.descriptorPool = GfxMgr::getInstance()->getDescriptorPool();
    allocInfo.descriptorSetCount = static_cast<uint32_t>(this->_swapChainFramebuffers.size());
    allocInfo.pSetLayouts = layouts.data();
    this->_descriptorSets.resize(this->_swapChainFramebuffers.size());
    VkResult result = vkAllocateDescriptorSets(GfxMgr::getInstance()->getVulkanDevice(), &allocInfo, this->_descriptorSets.data());

    if (result != VK_SUCCESS)
    {
        throw std::runtime_error("failed to allocate descriptor sets!");
    }
    // std::cout << "create descriptor set success..." << std::endl;

    for (size_t i = 0; i < this->_swapChainFramebuffers.size(); i++)
    {
        // VkDescriptorBufferInfo bufferInfo{};
        // bufferInfo.buffer = uniformBuffers[i];
        // bufferInfo.offset = 0;
        // bufferInfo.range = sizeof(UniformBufferObject);

        VkDescriptorImageInfo imageInfo{};
        imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
        imageInfo.imageView = this->_texture->getImageView();
        imageInfo.sampler = this->_texture->getSampler();

        std::array<VkWriteDescriptorSet, 1> descriptorWrites{};

        // descriptorWrites[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
        // descriptorWrites[0].dstSet = this->_descriptorSets[i];
        // descriptorWrites[0].dstBinding = 0;
        // descriptorWrites[0].dstArrayElement = 0;
        // descriptorWrites[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
        // descriptorWrites[0].descriptorCount = 1;
        // descriptorWrites[0].pBufferInfo = &bufferInfo;

        descriptorWrites[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
        descriptorWrites[0].dstSet = this->_descriptorSets[i];
        descriptorWrites[0].dstBinding = 1;
        descriptorWrites[0].dstArrayElement = 0;
        descriptorWrites[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
        descriptorWrites[0].descriptorCount = 1;
        descriptorWrites[0].pImageInfo = &imageInfo;

        vkUpdateDescriptorSets(GfxMgr::getInstance()->getVulkanDevice(), static_cast<uint32_t>(descriptorWrites.size()), descriptorWrites.data(), 0, nullptr);
        // std::cout << "update descriptor set success1111..." <<result<< std::endl;
        // if (result != VK_SUCCESS)
        // {
        //     throw std::runtime_error("failed to update descriptor sets!");
        // }
    }
}

void GfxObject::updateRender(uint32_t index)
{

    if (!this->_pipeline || this->_commandBuffers.empty() || this->_vertexBuffer == VK_NULL_HANDLE || this->_indexBuffer == VK_NULL_HANDLE)
        return;
    if (index >= this->_commandBuffers.size())
        return;


    vkResetCommandBuffer(this->_commandBuffers[index], VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT);

    VkCommandBufferBeginInfo beginInfo{};
    beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
    if (vkBeginCommandBuffer(this->_commandBuffers[index], &beginInfo) != VK_SUCCESS)
    {
        throw std::runtime_error("Failed to begin recording command buffer!");
    }
    // std::cout << "update render start..."<<this->_descriptorSets[index] << std::endl;
    // 添加图像布局转换屏障--待确定有用没
    VkImageMemoryBarrier barrier{};
    barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
    barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
    barrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
    barrier.image = GfxMgr::getInstance()->getSwapChainImages()[index]; // 使用当前交换链图像
    barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
    barrier.subresourceRange.baseMipLevel = 0;
    barrier.subresourceRange.levelCount = 1;
    barrier.subresourceRange.baseArrayLayer = 0;
    barrier.subresourceRange.layerCount = 1;
    barrier.srcAccessMask = 0;
    barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;

    vkCmdPipelineBarrier(
        this->_commandBuffers[index],
        VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
        VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
        0, 0, nullptr, 0, nullptr, 1, &barrier);

    // 开始渲染pass
    VkRenderPassBeginInfo renderPassInfo{};
    renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
    renderPassInfo.renderPass = this->_pipeline->getPass()->getVkRenderPass();

    renderPassInfo.framebuffer = this->_swapChainFramebuffers[index];

    renderPassInfo.renderArea.offset = {0, 0};
    renderPassInfo.renderArea.extent = GfxMgr::getInstance()->getSwapChainExtent();

    VkClearValue clearColor{};
    renderPassInfo.clearValueCount = 1;
    clearColor.color = {{this->_color[0], this->_color[1], this->_color[2], this->_color[3]}};
    renderPassInfo.pClearValues = &clearColor;

    vkCmdBeginRenderPass(this->_commandBuffers[index], &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
    if (this->_isClear)
    {
        VkClearAttachment clearAtt{};
        clearAtt.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
        clearAtt.clearValue.color = {{this->_color[0], this->_color[1], this->_color[2], this->_color[3]}}; // 红色，Alpha=0（透明）
        clearAtt.colorAttachment = 0;                                                                       // 第0个颜色附件

        VkClearRect clearRect{};
        clearRect.rect = renderPassInfo.renderArea; // 与 RenderPass 范围一致
        clearRect.baseArrayLayer = 0;
        clearRect.layerCount = 1;

        vkCmdClearAttachments(this->_commandBuffers[index], 1, &clearAtt, 1, &clearRect);
    }

    vkCmdBindPipeline(this->_commandBuffers[index], VK_PIPELINE_BIND_POINT_GRAPHICS, this->_pipeline->getVKPipeline());

    // 该函数用于提交绘制操作到指令缓冲
    // 参数1：需要执行的指令缓冲对象
    // 参数2：顶点缓冲数量
    // 参数3：用于实例渲染，为1时表示不进行实例渲染
    // 参数4：用于定义着色器变量gl_VertexIndex的值
    // 参数5：用于定义着色器变量gl_InstanceIndex的值

    // Render scene
    VkDeviceSize offsets[1] = {0};
    vkCmdBindVertexBuffers(this->_commandBuffers[index], 0, 1, &this->_vertexBuffer, offsets);
    vkCmdBindIndexBuffer(this->_commandBuffers[index], this->_indexBuffer, 0, VK_INDEX_TYPE_UINT32);

    // 绑定描述符集
    vkCmdBindDescriptorSets(this->_commandBuffers[index], VK_PIPELINE_BIND_POINT_GRAPHICS, this->_pipeline->getVKPipelineLayout(), 0, 1, &this->_descriptorSets[index], 0, nullptr);

    // 推送常量
    PushConstants pushConstants{};
    pushConstants.defaultColor[0] = this->_color[0];
    pushConstants.defaultColor[1] = this->_color[1];
    pushConstants.defaultColor[2] = this->_color[2];
    pushConstants.defaultColor[3] = this->_color[3];
    vkCmdPushConstants(this->_commandBuffers[index], this->_pipeline->getVKPipelineLayout(), VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(PushConstants), &pushConstants);
    vkCmdDrawIndexed(
        this->_commandBuffers[index],
        this->_indexSize, // 只绘制3个索引（第一个三角形）
        1,                // 实例数 （2的话代表绘制2个实例，也就是绘制两次）
        0,                // 第一个索引的偏移量
        0,                // 顶点偏移
        0                 // 实例偏移 孙菲菲
    );

    vkCmdEndRenderPass(this->_commandBuffers[index]);
    if (vkEndCommandBuffer(this->_commandBuffers[index]) != VK_SUCCESS)
    {
        throw std::runtime_error("Failed to record command buffer!");
    }
}
VkCommandBuffer GfxObject::getCommandBuffer(uint32_t index)
{
    return this->_commandBuffers[index];
}
void GfxObject::clear()
{
    // 销毁帧缓冲（Framebuffers）
    for (auto framebuffer : this->_swapChainFramebuffers)
    {
        vkDestroyFramebuffer(GfxMgr::getInstance()->getVulkanDevice(), framebuffer, nullptr);
    }
    this->_swapChainFramebuffers.clear();
    // 销毁命令缓冲（Command Buffers）
    if (!this->_commandBuffers.empty())

    {
        vkFreeCommandBuffers(GfxMgr::getInstance()->getVulkanDevice(), GfxMgr::getInstance()->getCommandPool(),
                             static_cast<uint32_t>(_commandBuffers.size()),
                             _commandBuffers.data());
        this->_commandBuffers.clear();
    }
}
void GfxObject::reset()
{
    this->_createFramebuffers();
}

GfxObject::~GfxObject()
{
}

// std::cout << "4444444..." << std::endl;
// std::cout << "create command buffer success" << std::endl;

// for (size_t i = 0; i < this->_commandBuffers.size(); i++)
// {
//     vkResetCommandBuffer(this->_commandBuffers[i], 0);

//     VkCommandBufferBeginInfo beginInfo{};
//     beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
//     if (vkBeginCommandBuffer(this->_commandBuffers[i], &beginInfo) != VK_SUCCESS)
//     {
//         throw std::runtime_error("Failed to begin recording command buffer!");
//     }
//     // std::cout << "00000000..." << std::endl;
//     // // 添加图像布局转换屏障--待确定有用没
//     // VkImageMemoryBarrier barrier{};
//     // barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
//     // barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
//     // barrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
//     // barrier.image = GfxMgr::getInstance()->getSwapChainImages()[i]; // 使用当前交换链图像
//     // barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
//     // barrier.subresourceRange.baseMipLevel = 0;
//     // barrier.subresourceRange.levelCount = 1;
//     // barrier.subresourceRange.baseArrayLayer = 0;
//     // barrier.subresourceRange.layerCount = 1;
//     // barrier.srcAccessMask = 0;
//     // barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;

//     // vkCmdPipelineBarrier(
//     //     this->_commandBuffers[i],
//     //     VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
//     //     VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
//     //     0, 0, nullptr, 0, nullptr, 1, &barrier);

//     // 开始渲染pass
//     VkRenderPassBeginInfo renderPassInfo{};
//     renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
//     renderPassInfo.renderPass = this->_pipeline->getPass()->getRenderPass();
//     renderPassInfo.framebuffer = this->_swapChainFramebuffers[i];
//     renderPassInfo.renderArea.offset = {0, 0};
//     renderPassInfo.renderArea.extent = GfxMgr::getInstance()->getSwapChainExtent();

//     VkClearValue clearColor{};
//     renderPassInfo.clearValueCount = 1;
//     clearColor.color = {{0.0f, 0.0f, 0.0f, 0.0f}};
//     renderPassInfo.pClearValues = &clearColor;

//     vkCmdBeginRenderPass(this->_commandBuffers[i], &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE);
//     // std::cout << "1111111..." << std::endl;
//     if (this->_isClear)
//     {
//         VkClearAttachment clearAtt{};
//         clearAtt.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
//         clearAtt.clearValue.color = {{0.0f, 0.0f, 0.0f, 0.0f}}; // 红色，Alpha=0（透明）
//         clearAtt.colorAttachment = 0;                           // 第0个颜色附件

//         VkClearRect clearRect{};
//         clearRect.rect = renderPassInfo.renderArea; // 与 RenderPass 范围一致
//         clearRect.baseArrayLayer = 0;
//         clearRect.layerCount = 1;

//         vkCmdClearAttachments(this->_commandBuffers[i], 1, &clearAtt, 1, &clearRect);
//     }

//     vkCmdBindPipeline(this->_commandBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, this->_pipeline->getPipeline());
//     // std::cout << "222222..." << std::endl;
//     // 该函数用于提交绘制操作到指令缓冲
//     // 参数1：需要执行的指令缓冲对象
//     // 参数2：顶点缓冲数量
//     // 参数3：用于实例渲染，为1时表示不进行实例渲染
//     // 参数4：用于定义着色器变量gl_VertexIndex的值
//     // 参数5：用于定义着色器变量gl_InstanceIndex的值

//     // Render scene
//     VkDeviceSize offsets[1] = {0};
//     vkCmdBindVertexBuffers(this->_commandBuffers[i], 0, 1, &this->_vertexBuffer, offsets);
//     vkCmdBindIndexBuffer(this->_commandBuffers[i], this->_indexBuffer, 0, VK_INDEX_TYPE_UINT32);

//     // 推送常量
//     PushConstants pushConstants{};
//     pushConstants.defaultColor[0] = this->_color[0];
//     pushConstants.defaultColor[1] = this->_color[1];
//     pushConstants.defaultColor[2] = this->_color[2];
//     pushConstants.defaultColor[3] = this->_color[3];
//     vkCmdPushConstants(this->_commandBuffers[i], this->_pipeline->getPipelineLayout(), VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(PushConstants), &pushConstants);
//     vkCmdDrawIndexed(
//         this->_commandBuffers[i],
//         this->_indexSize, // 只绘制3个索引（第一个三角形）
//         1,                // 实例数 （2的话代表绘制2个实例，也就是绘制两次）
//         0,                // 第一个索引的偏移量
//         0,                // 顶点偏移
//         0                 // 实例偏移
//     );

//     vkCmdEndRenderPass(this->_commandBuffers[i]);
//     // std::cout << "333333333..." << std::endl;
//     if (vkEndCommandBuffer(this->_commandBuffers[i]) != VK_SUCCESS)
//     {
//         throw std::runtime_error("Failed to record command buffer!");
//     }
//     // std::cout << "4444444..." << std::endl;
//     // std::cout << "create command buffer success" << std::endl;
// }